#include<iostream>
#include<vector>
#include<string>
#include<unistd.h>
#include<sys/wait.h>
#include"task.cc"
using namespace std;
//channel
class channel
{
public:
    channel(int wfd,int pid)
    :_wfd(wfd)
    ,_pid(pid)
    {
        _name="channel-"+to_string(_pid);
    }
    void getcode(int code)
    {
        int n=write(_wfd,&code,sizeof(code));
        (void)n;
    }
    void clode_wfd()
    {
        close(_wfd);
    }
    void wait_subpid()
    {
        waitpid(_pid,NULL,0);
    }
    string name()
    {
        return _name;
    }
    ~channel()
    {}
private:
    int _wfd;//该管道的写端
    int _pid;//该管道对应的子进程pid
    string _name;//该管道的名称
};
//管理channel的channelmanager
class channelmanager
{
public:
    channelmanager()
    :_next(0)
    {}
    channel& select()
    {
        auto& c=_channels[_next];
        _next++;
        _next=_next%_channels.size();//防止_next超出范围
        return c;
    }
    void insert(int wfd,int pid)
    {
        channel c(wfd,pid);
        _channels.push_back(c);
    }
    void close()
    {
        for(auto& c:_channels)
        {
            c.clode_wfd();
            cout<<"关闭管道"<<c.name()<<endl;
        }
    }
    void wait()
    {
        for(auto& c:_channels)
        {
            c.wait_subpid();
            cout<<"等待子进程"<<c.name()<<"结束"<<endl;
        }
    }
    
    ~channelmanager()
    {}
private:
    vector<channel> _channels;//使用vector管理channel
    int _next;
    int _code;
};
//进程池
class pool
{
public:
    pool(int num)
    :_num(num)
    {
        _tm.gettasks(printlog);
        _tm.gettasks(download);
        _tm.gettasks(upload);
        _tm.gettasks(compresstask);
        _tm.gettasks(decompresstask);
        _tm.gettasks(encrypt);
        _tm.gettasks(decrypt);
    }
    void work(int rfd)
    {
        while(1)
        {
            int code=0;
            ssize_t n=read(rfd,&code,sizeof(code));//将任务码读入code
            if(n<0)
            {
                cout<<"read error"<<endl;
                break;
            }
            else if(n==0)
            {
                cout<<"read end"<<endl;
                break;
            }
            else
            {
                if(n!=sizeof(code))//说明读入的不是任务码
                {
                    cout<<"read code error"<<endl;
                    continue;//接着读
                }
                //根据任务码执行相应的任务
                cout<<"子进程["<<getpid()<<"]接收到任务码:"<<code<<endl;
                _tm.execute(code);
            }
        }
    }
        
    bool start()
    {
        //首先使用fork创建num个子进程
        for(int i=0;i<_num;i++)
        {
            int pipefd[2]={0};
            int n=pipe(pipefd);
            if(n<0)//创建管道失败
            {
                cout<<"create pipe error"<<endl;
                return false;
            }
            //创建子进程
            pid_t pid=fork();
            if(pid<0)//fork失败
            {
                cout<<"fork error"<<endl;                
                return false;
            }
            //父写子读
            else if(pid==0)//子进程
            {
                cout<<"子进程["<<getpid()<<"]";
                //保证只有父亲一人指向写端
                _cm.close();
                //关闭写端
                close(pipefd[1]);
                work(pipefd[0]);
                close(pipefd[0]);
                //子进程退出
                exit(0);
            }
            else//父进程
            {
                //关闭读端
                close(pipefd[0]);
                //向channelmanager中添加channel
                _cm.insert(pipefd[1],pid);
            }
        }
    }
    void push_task()
    {
        auto& c=_cm.select();
        int taskcode=_tm.code();
        c.getcode(taskcode);
    }
    int get_tasknum()
    {
        return _tm.size();
    }
    void stop()
    {
        _cm.close();
        _cm.wait();
    }
    ~pool()
    {}
private:    
    channelmanager _cm;//管理channel的channelmanager
    taskmanager _tm;//管理任务的taskmanager
    int _num;//进程池中进程的数量
};